home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 30 / Mac Magazin and MacEasy Magazine CD - Issue 30.iso / utilities / Mac OS X / Flurry / Flurry source / Source Folder / Smoke.cpp < prev    next >
C/C++ Source or Header  |  2002-01-25  |  11KB  |  414 lines

  1. // Smoke.cpp: implementation of the Smoke class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4.  
  5. #include "Std.h"
  6. #include "Smoke.h"
  7. #include "Spark.h"
  8. #include "Star.h"
  9.  
  10. extern Spark spark[12];
  11. extern Star star;
  12. extern float gravity;
  13.  
  14. #define MAXANGLES 16384
  15. #define NOT_QUITE_DEAD 3
  16.  
  17. inline float FastDistance2D(float x, float y)
  18. {
  19.     // this function computes the distance from 0,0 to x,y with ~3.5% error
  20.     
  21.     // first compute the absolute value of x,y
  22.     x = (x < 0.0f) ? -x : x;
  23.     y = (y < 0.0f) ? -y : y;
  24.     
  25.     // compute the minimum of x,y
  26.     float mn = min(x,y);
  27.     
  28.     // return the distance
  29.     return(x+y-(mn*0.5f)-(mn*0.25f)+(mn*0.0625f));
  30.     
  31. } // end FastDistance2D
  32.  
  33. //////////////////////////////////////////////////////////////////////
  34. // Construction/Destruction
  35. //////////////////////////////////////////////////////////////////////
  36.  
  37. float intensity = 75000.0f;
  38.  
  39. Smoke::Smoke()
  40. {
  41.  
  42. }
  43.  
  44. Smoke::~Smoke()
  45. {
  46.     
  47. }
  48.  
  49. void Smoke::Update()
  50. {
  51.     static int nextParticle = 0;
  52.     static float lastParticleTime = 0.25f;
  53.     int i,j;
  54.     static float old[3];
  55.     static int firstTime = 1;
  56.     static long frame = 0;
  57.     float mPosX;
  58.     float mPosY;
  59.     float mPosZ;
  60.     float sx = star.position[0];
  61.     float sy = star.position[1];
  62.     float sz = star.position[2];
  63.  
  64.     frame++;
  65.  
  66.     if (!firstTime)
  67.     {
  68.         // release 12 puffs every frame
  69.         if (fTime-lastParticleTime >= 1.0f / 121.0f) 
  70.         {
  71.             float dx,dy,dz;
  72.             float f;
  73.             float rsquared;
  74.             int whichSpark = 0;
  75.             float mag;
  76.             
  77.             dx = old[0] - sx;
  78.             dy = old[1] - sy;
  79.             dz = old[2] - sz;
  80.             //rsquared = (dx*dx+dy*dy+dz*dz);
  81.             mag = 5.0f;// / (float) sqrt(rsquared);
  82.             float deltax = (dx * mag);
  83.             float deltay = (dy * mag);
  84.             float deltaz = (dz * mag);
  85.             for (i=0;i<numStreams;i++)
  86.             {
  87.                 p[nextParticle].delta[0] = deltax;
  88.                 p[nextParticle].delta[1] = deltay;
  89.                 p[nextParticle].delta[2] = deltaz;
  90.                 p[nextParticle].position[0] = sx;
  91.                 p[nextParticle].position[1] = sy;
  92.                 p[nextParticle].position[2] = sz;
  93.                 p[nextParticle].oldposition[0] = sx;
  94.                 p[nextParticle].oldposition[1] = sy;
  95.                 p[nextParticle].oldposition[2] = sz;
  96.                 float streamSpeedCoherenceFactor = max(0.0f,1.0f + RandBell(0.25f*incohesion));
  97.                 if (MouseDown)
  98.                 {
  99.                     mPosZ = sz;
  100.                     mPosX = (MouseX - sys_glWidth * 0.5f) / (sys_glWidth / mPosZ);
  101.                     mPosY = (sys_glHeight * 0.5f - MouseY) / (sys_glWidth / mPosZ);
  102.                     dx = p[nextParticle].position[0] - mPosX;
  103.                     dy = p[nextParticle].position[1] - mPosY;
  104.                     dz = p[nextParticle].position[2] - mPosZ;
  105.                     rsquared = (dx*dx+dy*dy+dz*dz);
  106.                     mag = streamSpeed * 0.05f * streamSpeedCoherenceFactor / (float) sqrt(rsquared);
  107.                     p[nextParticle].delta[0] -= (dx * mag);
  108.                     p[nextParticle].delta[1] -= (dy * mag);
  109.                     p[nextParticle].delta[2] -= (dz * mag);
  110.                 }
  111.                 dx = p[nextParticle].position[0] - spark[i].position[0];
  112.                 dy = p[nextParticle].position[1] - spark[i].position[1];
  113.                 dz = p[nextParticle].position[2] - spark[i].position[2];
  114.                 rsquared = (dx*dx+dy*dy+dz*dz);
  115.                 f = streamSpeed * streamSpeedCoherenceFactor;
  116.                 mag = f / (float) sqrt(rsquared);
  117.                 p[nextParticle].delta[0] -= (dx * mag);
  118.                 p[nextParticle].delta[1] -= (dy * mag);
  119.                 p[nextParticle].delta[2] -= (dz * mag);
  120.                 p[nextParticle].color[0] = spark[i].color[0] * (1.0f + RandBell(colorIncoherence));// + RandBell(0.25f*colorIncoherence);
  121.                 p[nextParticle].color[1] = spark[i].color[1] * (1.0f + RandBell(colorIncoherence));// + RandBell(0.25f*colorIncoherence);
  122.                 p[nextParticle].color[2] = spark[i].color[2] * (1.0f + RandBell(colorIncoherence));// + RandBell(0.25f*colorIncoherence);
  123.                 p[nextParticle].color[3] = 0.85f * (1.0f + RandBell(0.5f*colorIncoherence));// + RandBell(0.125f*colorIncoherence);
  124.                 p[nextParticle].dead = FALSE;
  125.                 p[nextParticle].time = fTime;
  126.                 p[nextParticle].animFrame = rand()&63;
  127.                 nextParticle++;
  128.                 if (nextParticle == NUMSMOKEPARTICLES)
  129.                 {
  130.                     nextParticle = 0;
  131.                 }
  132.             }
  133.             lastParticleTime = fTime;
  134.         }
  135.     }
  136.     else
  137.     {
  138.         lastParticleTime = fTime;
  139.         firstTime = 0;
  140.     }
  141.  
  142.     for (i=0;i<3;i++)
  143.     {
  144.         old[i] = star.position[i];
  145.     }
  146.     
  147.     if (MouseDown)
  148.     {
  149.         mPosZ = seraphDistance;
  150.         mPosX = (MouseX - sys_glWidth * 0.5f) / (sys_glWidth / mPosZ);
  151.         mPosY = (sys_glHeight * 0.5f - MouseY) / (sys_glWidth / mPosZ);
  152.     }
  153.  
  154. //    double frameRate = ((double) dframe)/(fTime -fTimeOffset);
  155.     double frameRateModifier = fDeltaTime * 42.5f;
  156. //    double frameRateModifier = 42.5f / frameRate;
  157.  
  158.     for (i=0;i<NUMSMOKEPARTICLES;i++)
  159.     {        
  160.         if (p[i].dead)
  161.         {
  162.             continue;
  163.         }
  164.  
  165.         float dx,dy,dz;
  166.         float f;
  167.         float rsquared;
  168.         float mag;
  169.         float deltax = p[i].delta[0];
  170.         float deltay = p[i].delta[1];
  171.         float deltaz = p[i].delta[2];
  172.  
  173.         
  174. //        if (MouseDown)
  175. //        {
  176. //            mPosZ = (p[i].position[2] + star.position[2]) * 0.5f;
  177. //            mPosX = (MouseX - sys_glWidth * 0.5f) / (sys_glWidth / mPosZ);
  178. //            mPosY = (sys_glHeight * 0.5f - MouseY) / (sys_glWidth / mPosZ);
  179. //        }
  180.         
  181.         for (j=0;j<numStreams;j++)
  182.         {
  183.             dx = p[i].position[0] - spark[j].position[0];
  184.             dy = p[i].position[1] - spark[j].position[1];
  185.             dz = p[i].position[2] - spark[j].position[2];
  186.             rsquared = (dx*dx+dy*dy+dz*dz);
  187.             f = (gravity/rsquared) * frameRateModifier;
  188.             if ((i % numStreams) == j)
  189.             {
  190. //                if (MouseDown)
  191. //                {
  192. //                    f *= 1.0f + streamBias * 0.25f;
  193. //                }
  194. //                else
  195. //                {
  196.                     f *= 1.0f + streamBias;
  197. //                }
  198.             }
  199.             
  200.             mag = f / (float) sqrt(rsquared);
  201.             
  202.             deltax -= (dx * mag);
  203.             deltay -= (dy * mag);
  204.             deltaz -= (dz * mag);
  205.         }
  206.         
  207.         if (MouseDown)
  208.         { 
  209.             dx = p[i].position[0] - mPosX;
  210.             dy = p[i].position[1] - mPosY;
  211.             dz = p[i].position[2] - mPosZ;
  212.             rsquared = (dx*dx+dy*dy+dz*dz);
  213.             f = (gravity/rsquared) * frameRateModifier;
  214.             f *= (1.0f + streamBias) * 0.5f;
  215.             mag = f / (float) sqrt(rsquared) ;
  216.             deltax -= (dx * mag);
  217.             deltay -= (dy * mag);
  218.             deltaz -= (dz * mag);
  219.         }
  220.         
  221.         // slow this particle down by drag
  222.         deltax *= drag;
  223.         deltay *= drag;
  224.         deltaz *= drag;
  225.         
  226.         if ((deltax*deltax+deltay*deltay+deltaz*deltaz) >= 25000000.0f)
  227.         {
  228.             p[i].dead = TRUE;
  229.             continue;
  230.         }
  231.  
  232.         // update the position
  233.         p[i].delta[0] = deltax;
  234.         p[i].delta[1] = deltay;
  235.         p[i].delta[2] = deltaz;
  236.         for (j=0;j<3;j++)
  237.         {
  238.             p[i].oldposition[j] = p[i].position[j];
  239.             p[i].position[j] += p[i].delta[j]*fDeltaTime;
  240.         }
  241.     }
  242. }
  243.  
  244. void Smoke::Draw()
  245. {
  246.     static float seraphimVertices[NUMSMOKEPARTICLES*2*4];
  247.     static float seraphimColors[NUMSMOKEPARTICLES*4*4];
  248.     static float seraphimTextures[NUMSMOKEPARTICLES*2*4];
  249.     int svi = 0;
  250.     int sci = 0;
  251.     int sti = 0;
  252.     int si = 0;
  253.     float width,sx,sy;
  254.     float u0,v0,u1,v1;
  255.     float w,z;
  256.     static int firstTime = 1;
  257.     if (firstTime)
  258.     {
  259.         firstTime = 0;
  260.     }
  261.  
  262.     static long frame = 0;
  263.     static float lastFrameTime = 0.0f;
  264.  
  265.     {
  266.         frame++;
  267.         lastFrameTime = fTime;
  268.     }
  269.  
  270.     float screenRatio = sys_glWidth / 1024.0f;
  271.  
  272.     width = (streamSize+2.5f*streamExpansion) * screenRatio;
  273.  
  274. //    glBegin(GL_QUADS);
  275.  
  276.     float hslash2 = sys_glHeight * 0.5f;
  277.     float wslash2 = sys_glWidth * 0.5f;
  278.  
  279.     for (int i=0;i<NUMSMOKEPARTICLES;i++)
  280.     {
  281.         if (p[i].dead == TRUE)
  282.         {
  283.             continue;
  284.         }
  285.         float thisWidth = (streamSize+(fTime-p[i].time)*streamExpansion) * screenRatio;
  286.         if (thisWidth >= width)
  287.         {
  288.             p[i].dead = TRUE;
  289.             continue;
  290.         }
  291.         z = p[i].position[2];
  292.         sx = p[i].position[0] * sys_glWidth / z + wslash2;
  293.         sy = p[i].position[1] * sys_glWidth / z + hslash2;
  294.         float oldz = p[i].oldposition[2];
  295.         if (sx > sys_glWidth+50.0f || sx < -50.0f || sy > sys_glHeight+50.0f || sy < -50.0f || z < 25.0f || oldz < 25.0f)
  296.         {
  297.             continue;
  298.         }
  299.  
  300.         w = max(1.0f,thisWidth/z);
  301. //        if (p[i].dead == NOT_QUITE_DEAD)
  302. //        {
  303. //            w *= 0.25f;
  304. //        }
  305.         float oldx = p[i].oldposition[0];
  306.         float oldy = p[i].oldposition[1];
  307.         float oldscreenx = (oldx * sys_glWidth / oldz) + wslash2;
  308.         float oldscreeny = (oldy * sys_glWidth / oldz) + hslash2;
  309.         float dx = (sx-oldscreenx);
  310.         float dy = (sy-oldscreeny);
  311.                 
  312.         float d = FastDistance2D(dx, dy);
  313.         
  314.         float s;
  315.         if (d)
  316.         {
  317.             s = w/d;
  318.         }
  319.         else
  320.         {
  321.             s = 0.0f;
  322.         }
  323.         float os;
  324.         float ow = max(1.0f,thisWidth/oldz);
  325.         if (d)
  326.         {
  327.             os = ow/d;
  328.         }
  329.         else
  330.         {
  331.             os = 0.0f;
  332.         }
  333.  
  334.         float m = 1.0f + s; 
  335.  
  336.         float dxs = dx*s;
  337.         float dys = dy*s;
  338.         float dxos = dx*os;
  339.         float dyos = dy*os;
  340.         float dxm = dx*m;
  341.         float dym = dy*m;
  342.  
  343.         p[i].animFrame++;
  344.         if (p[i].animFrame >= 64)
  345.         {
  346.             p[i].animFrame = 0;
  347.         }
  348.  
  349.         u0 = (p[i].animFrame&&7) * 0.125f;
  350.         v0 = (p[i].animFrame>>3) * 0.125f;
  351.         u1 = u0 + 0.125f;
  352.         v1 = v0 + 0.125f;
  353.         u1 = u0 + 0.125f;
  354.         v1 = v0 + 0.125f;
  355.         float cm = (1.375f - thisWidth/width);
  356.         if (p[i].dead == 3)
  357.         {
  358.             cm *= 0.125f;
  359.             p[i].dead = TRUE;
  360.         }
  361. //        glColor4f(p[i].color[0]*cm,p[i].color[1]*cm,p[i].color[2]*cm,p[i].color[3]*cm);
  362.         si++;
  363.         float cm0 = p[i].color[0]*cm;
  364.         float cm1 = p[i].color[1]*cm;
  365.         float cm2 = p[i].color[2]*cm;
  366.         float cm3 = p[i].color[3]*cm;
  367.         seraphimColors[sci++] = cm0;
  368.         seraphimColors[sci++] = cm1;
  369.         seraphimColors[sci++] = cm2;
  370.         seraphimColors[sci++] = cm3;
  371.         seraphimColors[sci++] = cm0;
  372.         seraphimColors[sci++] = cm1;
  373.         seraphimColors[sci++] = cm2;
  374.         seraphimColors[sci++] = cm3;
  375.         seraphimColors[sci++] = cm0;
  376.         seraphimColors[sci++] = cm1;
  377.         seraphimColors[sci++] = cm2;
  378.         seraphimColors[sci++] = cm3;
  379.         seraphimColors[sci++] = cm0;
  380.         seraphimColors[sci++] = cm1;
  381.         seraphimColors[sci++] = cm2;
  382.         seraphimColors[sci++] = cm3;
  383. //        glTexCoord2f(u0,v0);
  384.         seraphimTextures[sti++] = u0;
  385.         seraphimTextures[sti++] = v0;
  386. //        glVertex2f(sx+dxm-dys,sy+dym+dxs);
  387.         seraphimVertices[svi++] = sx+dxm-dys;
  388.         seraphimVertices[svi++] = sy+dym+dxs;
  389. //        glTexCoord2f(u0,v1);
  390.         seraphimTextures[sti++] = u0;
  391.         seraphimTextures[sti++] = v1;
  392. //        glVertex2f(sx+dxm+dys,sy+dym-dxs);
  393.         seraphimVertices[svi++] = sx+dxm+dys;
  394.         seraphimVertices[svi++] = sy+dym-dxs;
  395. //        glTexCoord2f(u1,v1);
  396.         seraphimTextures[sti++] = u1;
  397.         seraphimTextures[sti++] = v1;
  398. //        glVertex2f(oldscreenx-dxm+dyos,oldscreeny-dym-dxos);        
  399.         seraphimVertices[svi++] = oldscreenx-dxm+dyos;
  400.         seraphimVertices[svi++] = oldscreeny-dym-dxos;
  401. //        glTexCoord2f(u1,v0);
  402.         seraphimTextures[sti++] = u1;
  403.         seraphimTextures[sti++] = v0;
  404. //        glVertex2f(oldscreenx-dxm-dyos,oldscreeny-dym+dxos);
  405.         seraphimVertices[svi++] = oldscreenx-dxm-dyos;
  406.         seraphimVertices[svi++] = oldscreeny-dym+dxos;
  407.     }
  408. //    glEnd();
  409.     glColorPointer(4,GL_FLOAT,0,seraphimColors);
  410.     glVertexPointer(2,GL_FLOAT,0,seraphimVertices);
  411.     glTexCoordPointer(2,GL_FLOAT,0,seraphimTextures);
  412.     glDrawArrays(GL_QUADS,0,si*4);
  413. }
  414.